package com.scheduler.backend.blImpl;

import com.scheduler.backend.aps.domain.deadlinefirst.ScheduleTable;
import com.scheduler.backend.bl.PeopleService;
import com.scheduler.backend.data.repository.OrderSliceRepository;
import com.scheduler.backend.data.repository.ResourceGroupRepository;
import com.scheduler.backend.data.repository.ResourceRepository;
import com.scheduler.backend.po.OrderSlicePO;
import com.scheduler.backend.po.OrderSliceToEmployeeGroup;
import com.scheduler.backend.po.Resource;
import com.scheduler.backend.vo.ReUseRatio;
import com.scheduler.backend.vo.ResponseVO;
import com.scheduler.backend.vo.StaffGanttInfo;
import com.scheduler.backend.vo.WorkForOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

@Service
public class PeopleServiceImpl implements PeopleService {

    private static Logger logger = (Logger) LoggerFactory.getLogger(PeopleServiceImpl.class);

    private LocalDateTime scheduleStartTime = LocalDateTime.of(LocalDate.of(2018, 10, 14),
            LocalTime.of(7, 0, 0));;//todo 未来修改

    @Autowired
    private ResourceRepository resourceRepository;

    @Autowired
    private ResourceGroupRepository resourceGroupRepository;

    @Autowired
    private OrderSliceRepository orderSliceRepository;

    @Override
    public ResponseVO getStaffGanttByDate(Date date) {
        try{
            List<StaffGanttInfo> staffGanttInfoList = new ArrayList<>();
            List<Resource> oldResources = resourceRepository.findAll();
            List<Resource> newResources = new ArrayList<>();
            List<OrderSlicePO> orderSliceList = orderSliceRepository.findAll();
            orderSliceList.sort(Comparator.comparingLong(OrderSlicePO::getStartTimeSlot));

            for (int i=0;i<oldResources.size();i++){
                Resource resource = oldResources.get(i);
                if (resource.getResourceName().equals("班组")){
                    newResources.add(resource);
                }
            }
            List<OrderSliceToEmployeeGroup> oldList = resourceGroupRepository.findAll();
            for (int i=0;i<newResources.size();i++){
                Resource resource = newResources.get(i);
                StaffGanttInfo staffGanttInfo = new StaffGanttInfo();
                staffGanttInfo.setResourceName(resource.getResourceId());
                List<WorkForOrder> workForOrderList = new ArrayList<>();
                for (int j=0;j<orderSliceList.size();j++){
                    boolean pd = false;
                    List<OrderSliceToEmployeeGroup> newList = new ArrayList<>();
                    for (int k=0;k<oldList.size();k++){
                        if (orderSliceList.get(j).getId().startsWith(oldList.get(k).getId())){
                            newList.add(oldList.get(k));
                        }
                    }
                    for (int k=0;k<newList.size();k++){
                        if (newList.get(k).getEmployeeGroupID().equals(resource.getResourceId())){
                            pd = true;
                        }
                    }
                    if (!pd) continue;

                    LocalDateTime startTime = scheduleStartTime.plusSeconds(orderSliceList.get(j).getStartTimeSlot() * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime endTime = scheduleStartTime.plusSeconds((orderSliceList.get(j).getStartTimeSlot() + ScheduleTable.ORDER_SLICE_TIMESLOT_SPAN ) * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime today = date.toInstant()
                            .atZone( ZoneId.systemDefault() )
                            .toLocalDateTime();
                    if (startTime.toLocalDate().isEqual(today.toLocalDate())){
                        WorkForOrder workForOrder = new WorkForOrder();
                        workForOrder.setProductName(orderSliceList.get(j).getOrderID());
                        //workForOrder.setItemID(orderSliceList.get(j).getProductID());
                        workForOrder.setStartTime(Date.from(startTime.atZone( ZoneId.systemDefault()).toInstant()));
                        workForOrder.setEndTime(Date.from(endTime.atZone( ZoneId.systemDefault()).toInstant()));
                        workForOrderList.add(workForOrder);
                    }

                }
                staffGanttInfo.setProducts(workForOrderList);
                staffGanttInfoList.add(staffGanttInfo);
            }

            return ResponseVO.buildSuccess(staffGanttInfoList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getStaffGanttByDate Failed!");
        }
    }

    @Override
    public ResponseVO getStaffLoadRatioByDateInHour(Date date) {
        try{
            List<ReUseRatio> reUseRatioList = new ArrayList<>();

            List<Resource> oldResources = resourceRepository.findAll();
            List<Resource> newResources = new ArrayList<>();
            List<OrderSlicePO> orderSliceList = orderSliceRepository.findAll();
            orderSliceList.sort(Comparator.comparingLong(OrderSlicePO::getStartTimeSlot));

            for (int i=0;i<oldResources.size();i++){
                Resource resource = oldResources.get(i);
                if (resource.getResourceName().equals("班组")){
                    newResources.add(resource);
                }
            }

            LocalDateTime thisHour = date.toInstant()
                    .atZone( ZoneId.systemDefault() )
                    .toLocalDateTime();
            LocalDateTime nextHour = thisHour.plusHours(1);
            List<OrderSliceToEmployeeGroup> oldList = resourceGroupRepository.findAll();
            for (int i=0;i<newResources.size();i++){
                Resource resource = newResources.get(i);
                ReUseRatio reUseRatio = new ReUseRatio();
                reUseRatio.setResourceName(resource.getResourceId());
                double ratio = 0.0;
                double sumUp = 0.0;
                double sumDown = Duration.between(thisHour,nextHour).toMinutes();
                for (int j=0;j<orderSliceList.size();j++){
                    boolean pd = false;
                    List<OrderSliceToEmployeeGroup> newList = new ArrayList<>();
                    for (int k=0;k<oldList.size();k++){
                        if (orderSliceList.get(j).getId().startsWith(oldList.get(k).getId())){
                            newList.add(oldList.get(k));
                        }
                    }
                    for (int k=0;k<newList.size();k++){
                        if (newList.get(k).getEmployeeGroupID().equals(resource.getResourceId())){
                            pd = true;
                        }
                    }
                    if (!pd) continue;

                    LocalDateTime startTime = scheduleStartTime.plusSeconds(orderSliceList.get(j).getStartTimeSlot() * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime endTime = scheduleStartTime.plusSeconds((orderSliceList.get(j).getStartTimeSlot() + ScheduleTable.ORDER_SLICE_TIMESLOT_SPAN ) * 60 * ScheduleTable.ORDER_SLICE_MINUTES);

                    if ( (startTime.isEqual(thisHour)||startTime.isAfter(thisHour)) && (endTime.isEqual(nextHour)||endTime.isBefore(nextHour)) ){
                        sumUp += Math.abs(Duration.between(endTime,startTime).toMinutes());
                    }else if ( ((startTime.isEqual(thisHour)||startTime.isAfter(thisHour))) &&  ((startTime.isEqual(nextHour)||startTime.isBefore(nextHour)))){
                        sumUp += Math.abs(Duration.between(nextHour,startTime).toMinutes());
                    }else if (((endTime.isEqual(nextHour)||endTime.isBefore(nextHour))) && ((endTime.isEqual(thisHour)||endTime.isAfter(thisHour)))  ){
                        sumUp += Math.abs(Duration.between(endTime,thisHour).toMinutes());
                    }else if (((startTime.isEqual(thisHour)||startTime.isBefore(thisHour))) && ((endTime.isEqual(nextHour)||endTime.isAfter(nextHour)))){
                        sumUp += Math.abs(Duration.between(nextHour,thisHour).toMinutes());
                    }
                }
                if (sumDown>0.0){
                    ratio = sumUp / sumDown;
                }
                ratio = (double) Math.round(ratio * 1000) / 10;
                reUseRatio.setLoadRatio(ratio);
                reUseRatioList.add(reUseRatio);
            }

            return ResponseVO.buildSuccess(reUseRatioList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getStaffLoadRatioByDateInHour Failed!");
        }
    }

    @Override
    public ResponseVO getStaffLoadRatioByDateInDay(Date date) {
        try{
            List<ReUseRatio> reUseRatioList = new ArrayList<>();

            List<Resource> oldResources = resourceRepository.findAll();
            List<Resource> newResources = new ArrayList<>();
            List<OrderSlicePO> orderSliceList = orderSliceRepository.findAll();
            orderSliceList.sort(Comparator.comparingLong(OrderSlicePO::getStartTimeSlot));

            for (int i=0;i<oldResources.size();i++){
                Resource resource = oldResources.get(i);
                if (resource.getResourceName().equals("班组")){
                    newResources.add(resource);
                }
            }

            LocalDateTime today = date.toInstant()
                    .atZone( ZoneId.systemDefault() )
                    .toLocalDateTime();
            LocalDateTime tomorrow = today.plusDays(1);
            List<OrderSliceToEmployeeGroup> oldList = resourceGroupRepository.findAll();
            for (int i=0;i<newResources.size();i++){
                Resource resource = newResources.get(i);
                ReUseRatio reUseRatio = new ReUseRatio();
                reUseRatio.setResourceName(resource.getResourceId());
                double ratio = 0.0;
                double sumUp = 0.0;
                double sumDown = Duration.between(today,tomorrow).toMinutes();
                for (int j=0;j<orderSliceList.size();j++){

                    boolean pd = false;
                    List<OrderSliceToEmployeeGroup> newList = new ArrayList<>();
                    for (int k=0;k<oldList.size();k++){
                        if (orderSliceList.get(j).getId().startsWith(oldList.get(k).getId())){
                            newList.add(oldList.get(k));
                        }
                    }
                    for (int k=0;k<newList.size();k++){
                        if (newList.get(k).getEmployeeGroupID().equals(resource.getResourceId())){
                            pd = true;
                        }
                    }
                    if (!pd) continue;

                    LocalDateTime startTime = scheduleStartTime.plusSeconds(orderSliceList.get(j).getStartTimeSlot() * 60 * ScheduleTable.ORDER_SLICE_MINUTES);
                    LocalDateTime endTime = scheduleStartTime.plusSeconds((orderSliceList.get(j).getStartTimeSlot() + ScheduleTable.ORDER_SLICE_TIMESLOT_SPAN ) * 60 * ScheduleTable.ORDER_SLICE_MINUTES);

                    if (startTime.toLocalDate().isEqual(today.toLocalDate()) && endTime.toLocalDate().isEqual(today.toLocalDate())){
                        sumUp += Math.abs(Duration.between(endTime,startTime).toMinutes());
                    }else if (startTime.toLocalDate().isEqual(today.toLocalDate())){
                        sumUp += Math.abs(Duration.between(tomorrow,startTime).toMinutes());
                    }else if (endTime.toLocalDate().isEqual(today.toLocalDate())){
                        sumUp += Math.abs(Duration.between(today,endTime).toMinutes());
                    }
                }
                if (sumDown>0.0){
                    ratio = sumUp / sumDown;
                }
                ratio = (double) Math.round(ratio * 1000) / 10;
                reUseRatio.setLoadRatio(ratio);
                reUseRatioList.add(reUseRatio);
            }

            return ResponseVO.buildSuccess(reUseRatioList);
        }catch (Exception e){
            return ResponseVO.buildFailure("getStaffLoadRatioByDateInDay Failed!");
        }
    }
}